home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / BORL_TIP / TI100 / TI226.ASC < prev    next >
Text File  |  1991-09-11  |  26KB  |  991 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  10.   VERSION : 3.0xx
  11.        OS : PC-DOS
  12.      DATE : August 1, 1986                              PAGE : 1/15
  13.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  14.  
  15.  
  16.  
  17.  
  18.   This version of Michael Quinlan's ASYNC.INC is compatible with
  19.   IBM PC and Compatibles. It gives interrupt-driven buffered
  20.   communication capabilities to Turbo programs written for the IBM
  21.   PC. It is heavily dependent on that hardware.
  22.  
  23.   **NOTE: Pages 12 through 15 contain an additional routine that
  24.   allows your program to change the communications parameters.
  25.  
  26.   The following example routines are public domain programs that
  27.   have been uploaded to our Forum on CompuServe. As a courtesy to
  28.   our users that do not have immediate access to CompuServe,
  29.   Technical Support distributes these routines free of charge.
  30.  
  31.   However, because these routines are public domain programs, not
  32.   developed by Borland International, we are unable to provide any
  33.   technical support or assistance using these routines. If you need
  34.   assistance using these routines, or are experiencing
  35.   difficulties, we recommend that you log onto CompuServe and
  36.   request assistance from the Forum members that developed these
  37.   routines.
  38.  
  39.   {--------------------------------------------------------------}
  40.   {                        ASYNC.INC                             }
  41.   {                                                              }
  42.   {  Async Communication Routines                                }
  43.   {  by Michael Quinlan                                          }
  44.   {  with a bug fixed by Scott Herr                              }
  45.   {  made PCjr-compatible by W. M. Miller                        }
  46.   {  Highly dependent on the IBM PC and PC DOS 2.0               }
  47.   {                                                              }
  48.   {  based on the DUMBTERM program by CJ Dunford                 }
  49.   {  in the January 1984                                         }
  50.   {  issue of PC Tech Journal.                                   }
  51.   {                                                              }
  52.   {  Entry points:                                               }
  53.   {    Async_Init                                                }
  54.   {      Performs initialization.                                }
  55.   {                                                              }
  56.   {    Async_Open(Port, Baud : Integer;                          }
  57.   {               Parity : Char;                                 }
  58.   {               WordSize, StpBits : Integer) : Boolean         }
  59.   {   Sets up interrupt vector, initialize the COM port for      }
  60.   {   processing, sets pointers to the buffer.  Returns FALSE    }
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  76.   VERSION : 3.0xx
  77.        OS : PC-DOS
  78.      DATE : August 1, 1986                              PAGE : 2/15
  79.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  80.  
  81.  
  82.  
  83.  
  84.   {   if COM                                                     }
  85.   {      port not installed.                                     }
  86.   {                                                              }
  87.   {    Async_Buffer_Check(var C : Char) : Boolean                }
  88.   {      If a character is available, returns TRUE and moves the }
  89.   {        character from the buffer to the parameter            }
  90.   {      Otherwise, returns FALSE                                }
  91.   {                                                              }
  92.   {    Async_Send(C : Char)                                      }
  93.   {      Transmits the character.                                }
  94.  
  95.   {    Async_Send_String(S : LStr)                               }
  96.   {      Calls Async_Send to send each character of S.           }
  97.   {    Async_Close                                               }
  98.   {    Turn off the COM port interrupts.                         }
  99.   {    **MUST** BE CALLED BEFORE EXITING                         }
  100.   {    YOUR PROGRAM; otherwise you                               }
  101.   {    will see some really strange errors and have to re-boot.  }
  102.   {--------------------------------------------------------------}
  103.   { global declarations }
  104.  
  105.   type
  106.     LStr = String[255];  { generic string type for parameters }
  107.  
  108.   const
  109.     UART_THR = $00;
  110.         { offset from base of UART Registers for IBM PC }
  111.     UART_RBR = $00;
  112.     UART_IER = $01;
  113.     UART_IIR = $02;
  114.     UART_LCR = $03;
  115.     UART_MCR = $04;
  116.     UART_LSR = $05;
  117.     UART_MSR = $06;
  118.  
  119.     I8088_IMR = $21;
  120.          { port address of the Interrupt Mask Register }
  121.  
  122.   const
  123.     Async_DSeg_Save : Integer = 0;
  124.                        { Save DS reg in Code Segment
  125.                        for interrupt routine }
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  142.   VERSION : 3.0xx
  143.        OS : PC-DOS
  144.      DATE : August 1, 1986                              PAGE : 3/15
  145.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  146.  
  147.  
  148.  
  149.  
  150.   const
  151.     Async_Buffer_Max = 4095;
  152.  
  153.   var
  154.     Async_Buffer    : Array[0..Async_Buffer_Max] of char;
  155.     Async_Open_Flag : Boolean;
  156.     Async_Port      : Integer; { current Open port number (1 or 2) }
  157.     Async_Base      : Integer; { base for current open port }
  158.     Async_Irq       : Integer; { irq for current open port }
  159.  
  160.     Async_Buffer_Overflow : Boolean;
  161.              { True if buffer overflow has happened }
  162.     Async_Buffer_Used     : Integer;
  163.     Async_MaxBufferUsed   : Integer;
  164.  
  165.       { Async_Buffer is empty if Head = Tail }
  166.     Async_Buffer_Head  : Integer;
  167.              { Locn in Async_Buffer to put next char }
  168.     Async_Buffer_Tail  : Integer;
  169.              { Locn in Async_Buffer to get next char }
  170.     Async_Buffer_NewTail : Integer;
  171.  
  172.     Async_BIOS_Port_Table : Array[1..2] of Integer absolute $40:0;
  173.       { This table is initialized by BIOS equipment determination
  174.       code at boot time to contain the base addresses for the
  175.       installed async adapters.  A value of 0 means "not in-
  176.       stalled." }
  177.  
  178.   const
  179.     Async_Num_Bauds = 8;
  180.     Async_Baud_Table : array [1..Async_Num_Bauds] of record
  181.                                            Baud, Bits : integer
  182.                                         end
  183.                      = ((Baud:110;  Bits:$00),
  184.                         (Baud:150;  Bits:$20),
  185.                         (Baud:300;  Bits:$40),
  186.                         (Baud:600;  Bits:$60),
  187.                         (Baud:1200; Bits:$80),
  188.                         (Baud:2400; Bits:$A0),
  189.                         (Baud:4800; Bits:$C0),
  190.                         (Baud:9600; Bits:$E0));
  191.  
  192.   procedure BIOS_RS232_Init(ComPort, ComParm : Integer);
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  208.   VERSION : 3.0xx
  209.        OS : PC-DOS
  210.      DATE : August 1, 1986                              PAGE : 4/15
  211.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  212.  
  213.  
  214.  
  215.  
  216.   { Issue Interrupt $14 to initialize the UART }
  217.   { See the IBM PC Technical Reference Manual
  218.     for the format of ComParm }
  219.   var
  220.     Regs : record
  221.              ax, bx, cx, dx, bp, si, di, ds, es, flag : Integer
  222.            end;
  223.   begin
  224.     with Regs do
  225.       begin
  226.         ax := ComParm and $00FF;  { AH=0; AL=ComParm }
  227.         dx := ComPort;
  228.         Intr($14, Regs)
  229.       end
  230.   end; { BIOS_RS232_Init }
  231.  
  232.   procedure DOS_Set_Intrpt(v, s, o : integer);
  233.   { call DOS to set an interrupt vector }
  234.   var
  235.     Regs : Record
  236.              ax, bx, cx, dx, bp, si, di, ds, es, flag : integer
  237.            end;
  238.   begin
  239.     with Regs do
  240.       begin
  241.         ax := $2500 + (v and $00FF);
  242.         ds := s;
  243.         dx := o;
  244.         MsDos(Regs)
  245.       end
  246.   end; { DOS_Set_Intrpt }
  247.  
  248.   {----------------------------------------------------------}
  249.   {                                                          }
  250.   {  ASYNCISR.INC - Interrupt Service Routine                }
  251.   {                                                          }
  252.   {----------------------------------------------------------}
  253.  
  254.   procedure Async_Isr;
  255.   { Interrupt Service Routine }
  256.   { Invoked when the UART has received a byte of data from the
  257.     communication line }
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  274.   VERSION : 3.0xx
  275.        OS : PC-DOS
  276.      DATE : August 1, 1986                              PAGE : 5/15
  277.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  278.  
  279.  
  280.  
  281.  
  282.   { re-written 9/14/84 to be entirely in machine language;
  283.     original source left as comments }
  284.  
  285.   begin
  286.  
  287.     {NOTE: on entry, Turbo Pascal has already PUSHed BP and SP }
  288.     Inline(
  289.         { save all registers used }
  290.       $50/                           { PUSH AX }
  291.       $53/                           { PUSH BX }
  292.       $52/                           { PUSH DX }
  293.       $1E/                           { PUSH DS }
  294.       $FB/                           { STI }
  295.      { set up the DS register to point to Turbo Pascal's data segment }
  296.       $2E/$FF/$36/Async_Dseg_Save/   { PUSH CS:Async_Dseg_Save }
  297.       $1F/                           { POP DS }
  298.      { get the incoming character }
  299.      { Async_Buffer[Async_Buffer_Head]
  300.                     := Chr(Port[UART_RBR + Async_Base]); }
  301.       $8B/$16/Async_Base/            { MOV DX,Async_Base }
  302.       $EC/                           { IN AL,DX }
  303.       $8B/$1E/Async_Buffer_Head/     { MOV BX,Async_Buffer_Head }
  304.       $88/$87/Async_Buffer/          { MOV Async_Buffer[BX],AL }
  305.         { Async_Buffer_NewHead := Async_Buffer_Head + 1; }
  306.       $43/                           { INC BX }
  307.         { if Async_Buffer_NewHead > Async_Buffer_Max then
  308.             Async_Buffer_NewHead := 0; }
  309.       $81/$FB/Async_Buffer_Max/      { CMP BX,Async_Buffer_Max }
  310.       $7E/$02/                       { JLE L001 }
  311.       $33/$DB/                       { XOR BX,BX }
  312.         { if Async_Buffer_NewHead = Async_Buffer_Tail then
  313.             Async_Buffer_Overflow := TRUE
  314.           else }
  315.   {L001:}
  316.      $3B/$1E/Async_Buffer_Tail/     { CMP BX,Async_Buffer_Tail }
  317.      $75/$08/                       { JNE L002 }
  318.      $C6/$06/Async_Buffer_Overflow/$01/ { MOV Async_Buffer_Overflow,1 }
  319.      $90/                           { NOP generated by assembler
  320.                                       for some reason }
  321.      $EB/$16/                       { JMP SHORT L003 }
  322.        { begin
  323.            Async_Buffer_Head := Async_Buffer_NewHead;
  324.            Async_Buffer_Used := Async_Buffer_Used + 1;
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  340.   VERSION : 3.0xx
  341.        OS : PC-DOS
  342.      DATE : August 1, 1986                              PAGE : 6/15
  343.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  344.  
  345.  
  346.  
  347.  
  348.            if Async_Buffer_Used > Async_MaxBufferUsed then
  349.              Async_MaxBufferUsed := Async_Buffer_Used
  350.          end; }
  351.   {L002:}
  352.      $89/$1E/Async_Buffer_Head/     { MOV Async_Buffer_Head,BX }
  353.      $FF/$06/Async_Buffer_Used/     { INC Async_Buffer_Used }
  354.      $8B/$1E/Async_Buffer_Used/     { MOV BX,Async_Buffer_Used }
  355.      $3B/$1E/Async_MaxBufferUsed/   { CMP BX,Async_MaxBufferUsed }
  356.      $7E/$04/                       { JLE L003 }
  357.      $89/$1E/Async_MaxBufferUsed/   { MOV Async_MaxBufferUsed,BX }
  358.   {L003:}
  359.        { disable interrupts }
  360.      $FA/                           { CLI }
  361.        { Port[$20] := $20; }  { use non-specific EOI }
  362.      $B0/$20/                       { MOV AL,20h }
  363.      $E6/$20/                       { OUT 20h,AL }
  364.        { restore the registers then use IRET to return }
  365.        { the last two POPs are required because Turbo Pascal
  366.          PUSHes these regs before we get control.  The manual
  367.          doesn't so it, but that is what really happens }
  368.      $1F/                           { POP DS }
  369.      $5A/                           { POP DX }
  370.      $5B/                           { POP BX }
  371.      $58/                           { POP AX }
  372.      $5C/                           { POP SP }
  373.      $5D/                           { POP BP }
  374.      $CF)                           { IRET }
  375.   end; { Async_Isr }
  376.  
  377.   procedure Async_Init;
  378.   { initialize variables }
  379.   begin
  380.     Async_DSeg_Save := DSeg;
  381.     Async_Open_Flag := FALSE;
  382.     Async_Buffer_Overflow := FALSE;
  383.     Async_Buffer_Used := 0;
  384.     Async_MaxBufferUsed := 0;
  385.   end; { Async_Init }
  386.  
  387.   procedure Async_Close;
  388.   { reset the interrupt system when UART interrupts
  389.     no longer needed }
  390.   var
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  406.   VERSION : 3.0xx
  407.        OS : PC-DOS
  408.      DATE : August 1, 1986                              PAGE : 7/15
  409.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  410.  
  411.  
  412.  
  413.  
  414.     i, m : Integer;
  415.   begin
  416.     if Async_Open_Flag then
  417.       begin
  418.  
  419.         { disable the IRQ on the 8259 }
  420.         Inline($FA);         { disable interrupts }
  421.         i := Port[I8088_IMR];
  422.                              { get the interrupt mask register }
  423.         m := 1 shl Async_Irq;
  424.                              { set mask to turn off interrupt }
  425.         Port[I8088_IMR] := i or m;
  426.  
  427.         { disable the 8250 data ready interrupt }
  428.         Port[UART_IER + Async_Base] := 0;
  429.  
  430.         { disable OUT2 on the 8250 }
  431.         Port[UART_MCR + Async_Base] := 0;
  432.         Inline($FB);          { enable interrupts }
  433.  
  434.         { re-initialize our data areas so
  435.           we know the port is closed }
  436.         Async_Open_Flag := FALSE
  437.  
  438.       end
  439.   end; { Async_Close }
  440.  
  441.   function Async_Open(ComPort       : Integer;
  442.                       BaudRate      : Integer;
  443.                       Parity        : Char;
  444.                       WordSize      : Integer;
  445.                       StopBits      : Integer) : Boolean;
  446.   { open a communications port }
  447.   var
  448.     ComParm : Integer;
  449.     i, m : Integer;
  450.   begin
  451.     if Async_Open_Flag then Async_Close;
  452.  
  453.     if (ComPort = 2) and (Async_BIOS_Port_Table[2] <> 0) then
  454.       Async_Port := 2
  455.     else
  456.       Async_Port := 1;  { default to COM1 }
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  472.   VERSION : 3.0xx
  473.        OS : PC-DOS
  474.      DATE : August 1, 1986                              PAGE : 8/15
  475.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  476.  
  477.  
  478.  
  479.  
  480.     Async_Base := Async_BIOS_Port_Table[Async_Port];
  481.     Async_Irq := Hi(Async_Base) + 1;
  482.  
  483.     if (Port[UART_IIR + Async_Base] and $00F8) <> 0 then
  484.       Async_Open := FALSE
  485.     else
  486.       begin
  487.         Async_Buffer_Head := 0;
  488.         Async_Buffer_Tail := 0;
  489.         Async_Buffer_Overflow := FALSE;
  490.  
  491.     { Build the ComParm for RS232_Init }
  492.     { See Technical Reference Manual for description }
  493.  
  494.         ComParm := $0000;
  495.  
  496.     { Set up the bits for the baud rate }
  497.         i := 0;
  498.         repeat
  499.           i := i + 1
  500.         until (Async_Baud_Table[i].Baud = BaudRate)
  501.                 or (i = Async_Num_Bauds);
  502.         ComParm := ComParm or Async_Baud_Table[i].Bits;
  503.  
  504.         if Parity in ['E', 'e'] then ComParm := ComParm or $0018
  505.         else if Parity in ['O', 'o'] then
  506.              ComParm := ComParm or $0008
  507.         else ComParm := ComParm or $0000;  { default to No parity }
  508.  
  509.         if WordSize = 7 then ComParm := ComParm or $0002
  510.         else ComParm := ComParm or $0003;  { default to 8 data bits }
  511.  
  512.         if StopBits = 2 then ComParm := ComParm or $0004
  513.         else ComParm := ComParm or $0000;  { default to 1 stop bit }
  514.  
  515.         { use the BIOS COM port initialization routine
  516.           to save typing the code }
  517.  
  518.         BIOS_RS232_Init(Async_Port - 1, ComParm);
  519.  
  520.         DOS_Set_Intrpt(Async_Irq + 8, CSeg, Ofs(Async_Isr));
  521.  
  522.   { read the RBR and reset any possible pending error conditions
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  538.   VERSION : 3.0xx
  539.        OS : PC-DOS
  540.      DATE : August 1, 1986                              PAGE : 9/15
  541.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  542.  
  543.  
  544.  
  545.  
  546.     first turn off the Divisor Access Latch Bit to allow
  547.     access to RBR, etc. }
  548.  
  549.         Inline($FA);  { disable interrupts }
  550.  
  551.         Port[UART_LCR + Async_Base] :=
  552.                 Port[UART_LCR + Async_Base] and $7F;
  553.         { read the Line Status Register to reset any
  554.           errors it indicates }
  555.         i := Port[UART_LSR + Async_Base];
  556.         { read the Receiver Buffer Register in case
  557.           it contains a character }
  558.         i := Port[UART_RBR + Async_Base];
  559.  
  560.         { enable the irq on the 8259 controller }
  561.         i := Port[I8088_IMR];  { get the interrupt mask register }
  562.         m := (1 shl Async_Irq) xor $00FF;
  563.         Port[I8088_IMR] := i and m;
  564.  
  565.         { enable the data ready interrupt on the 8250 }
  566.         Port[UART_IER + Async_Base] := $01;
  567.         { enable data ready interrupt }
  568.  
  569.         { enable OUT2 on 8250 }
  570.         i := Port[UART_MCR + Async_Base];
  571.         Port[UART_MCR + Async_Base] := i or $08;
  572.         Inline($FB); { enable interrupts }
  573.         Async_Open_Flag := TRUE;  { bug fix by Scott Herr }
  574.         Async_Open := TRUE
  575.       end
  576.   end; { Async_Open }
  577.  
  578.   function Async_Buffer_Check(var C : Char) : Boolean;
  579.   { see if a character has been received; return it if yes }
  580.   begin
  581.     if Async_Buffer_Head = Async_Buffer_Tail then
  582.       Async_Buffer_Check := FALSE
  583.     else
  584.       begin
  585.         C := Async_Buffer[Async_Buffer_Tail];
  586.         Async_Buffer_Tail := Async_Buffer_Tail + 1;
  587.         if Async_Buffer_Tail > Async_Buffer_Max then
  588.           Async_Buffer_Tail := 0;
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  604.   VERSION : 3.0xx
  605.        OS : PC-DOS
  606.      DATE : August 1, 1986                             PAGE : 10/15
  607.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  608.  
  609.  
  610.  
  611.  
  612.         Async_Buffer_Used := Async_Buffer_Used - 1;
  613.         Async_Buffer_Check := TRUE
  614.       end
  615.   end; { Async_Buffer_Check }
  616.  
  617.   procedure Async_Send(C : Char);
  618.   { transmit a character }
  619.   var
  620.     i, m, counter : Integer;
  621.   begin
  622.     Port[UART_MCR + Async_Base] := $0B; { turn on OUT2, DTR, and RTS }
  623.  
  624.     { wait for CTS }
  625.     counter := MaxInt;
  626.     while (counter <> 0) and
  627.           ((Port[UART_MSR + Async_Base] and $10) = 0) do
  628.       counter := counter - 1;
  629.  
  630.     { wait for Transmit Hold Register Empty (THRE) }
  631.     if counter <> 0 then counter := MaxInt;
  632.     while (counter <> 0) and
  633.           ((Port[UART_LSR + Async_Base] and $20) = 0) do
  634.       counter := counter - 1;
  635.     if counter <> 0 then
  636.       begin
  637.         { send the character }
  638.         Inline($FA); { disable interrupts }
  639.         Port[UART_THR + Async_Base] := Ord(C);
  640.         Inline($FB) { enable interrupts }
  641.       end
  642.     else
  643.       writeln('<<<TIMEOUT>>>');
  644.   end; { Async_Send }
  645.  
  646.   procedure Async_Send_String(S : LStr);
  647.   { transmit a string }
  648.   var
  649.     i : Integer;
  650.   begin
  651.     for i := 1 to length(S) do
  652.       Async_Send(S[i])
  653.   end; { Async_Send_String }
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  670.   VERSION : 3.0xx
  671.        OS : PC-DOS
  672.      DATE : August 1, 1986                             PAGE : 11/15
  673.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  674.  
  675.  
  676.  
  677.  
  678.   ________________________________________________________________
  679.  
  680.                           CHANGE PARAMETERS
  681.   ________________________________________________________________
  682.  
  683.  
  684.   { ASYCHG.INC - procedure to change communication parameters }
  685.   { "on the fly" must be Included following ASYNC.INC }
  686.  
  687.   procedure Async_Change(BaudRate      : Integer;
  688.                          Parity        : Char;
  689.                          WordSize      : Integer;
  690.                          StopBits      : Integer);
  691.   { change communication parameters "on the fly" }
  692.   { you cannot use the BIOS routines because they drop DTR }
  693.  
  694.   const num_bauds = 15;
  695.       divisor_table : array [1..num_bauds] of record
  696.                                               baud, divisor : integer
  697.                                             end
  698.          = ((baud:50;  divisor:2304),
  699.             (baud:75;  divisor:1536),
  700.             (baud:110; divisor:1047),
  701.             (baud:134; divisor:857),
  702.             (baud:150; divisor:768),
  703.             (baud:300; divisor:384),
  704.             (baud:600; divisor:192),
  705.             (baud:1200; divisor:96),
  706.             (baud:1800; divisor:64),
  707.             (baud:2000; divisor:58),
  708.             (baud:2400; divisor:48),
  709.             (baud:3600; divisor:32),
  710.             (baud:4800; divisor:24),
  711.             (baud:7200; divisor:16),
  712.             (baud:9600; divisor:12));
  713.  
  714.   var i : integer;
  715.       dv  : integer;
  716.       lcr : integer;
  717.  
  718.   begin
  719.  
  720.     { Build the Line Control Register and find
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  736.   VERSION : 3.0xx
  737.        OS : PC-DOS
  738.      DATE : August 1, 1986                             PAGE : 12/15
  739.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  740.  
  741.  
  742.  
  743.  
  744.       the divisor (for the baud rate) }
  745.  
  746.     { Set up the divisor for the baud rate }
  747.     i := 0;
  748.     repeat
  749.       i := i + 1
  750.     until (Divisor_Table[i].Baud = BaudRate) or (i = Num_Bauds);
  751.     dv  := Divisor_Table[i].divisor;
  752.  
  753.     lcr := 0;
  754.     case Parity of
  755.       'E' : lcr := lcr or $18;  { even parity }
  756.       'O' : lcr := lcr or $08;  { odd parity }
  757.       'N' : lcr := lcr or $00;  { no parity }
  758.       'M' : lcr := lcr or $28;  { Mark parity }
  759.       'S' : lcr := lcr or $38;  { Space parity }
  760.     else
  761.       lcr := lcr or $00;  { default to no parity }
  762.     end;
  763.  
  764.     case WordSize of
  765.       5 : lcr := lcr or $00;
  766.       6 : lcr := lcr or $01;
  767.       7 : lcr := lcr or $02;
  768.       8 : lcr := lcr or $03;
  769.     else
  770.       lcr := lcr or $03;  { default to 8 data bits }
  771.     end;
  772.  
  773.     if StopBits = 2 then lcr := lcr or $04
  774.     else lcr := lcr or $00;  { default to 1 stop bit }
  775.  
  776.     lcr := lcr and $7F;   { make certain the DLAB is off }
  777.  
  778.     Inline($FA);  { disable interrupts }
  779.  
  780.     { turn on DLAB to access the divisor }
  781.     Port[UART_LCR + Async_Base] := Port[UART_LCR + Async_Base] or $80;
  782.  
  783.     { set the divisor }
  784.     Port[Async_Base] := Lo(dv);
  785.     Port[Async_Base + 1] := Hi(dv);
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  802.   VERSION : 3.0xx
  803.        OS : PC-DOS
  804.      DATE : August 1, 1986                             PAGE : 13/15
  805.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  806.  
  807.  
  808.  
  809.  
  810.     { turn off the DLAB and set the new comm. parameters }
  811.     Port[UART_LCR + Async_Base] := lcr;
  812.  
  813.     Inline($FB);  { enable interrupts }
  814.  
  815.   end; { Async_Change }
  816.  
  817.   The following are two example programs which use ASYNC.INC.
  818.  
  819.     program DumbTerminal;
  820.     {$C-}
  821.     {$I ASYNC.INC}
  822.     var
  823.       ch: Char;
  824.       stop: Boolean;
  825.     begin
  826.       stop := false;
  827.       Async_Init;
  828.       if not Async_Open(1, 1200, 'E', 7, 1) then
  829.         begin
  830.           writeln('Invalid port');
  831.           Halt
  832.         end;
  833.       LowVideo;
  834.        writeln('COM1 now open at 1200 baud, 7 data bits, even parity, ',
  835.               '1 stop bit.');
  836.       write('All keyboard input will be sent out COM1');
  837.       writeln('all input from COM1');
  838.       writeln('will be displayed on the screen.  To quit, type ^Z.');
  839.       writeln;
  840.       repeat
  841.         if Async_Buffer_Check(ch) then write(ch);
  842.         if KeyPressed then
  843.           begin
  844.             read(Kbd, ch);
  845.             if ch = ^Z then stop := true else Async_Send(ch)
  846.           end
  847.       until stop;
  848.       Async_Close
  849.     end.
  850.  
  851.   program tty;
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  868.   VERSION : 3.0xx
  869.        OS : PC-DOS
  870.      DATE : August 1, 1986                             PAGE : 14/15
  871.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  872.  
  873.  
  874.  
  875.  
  876.   {$IASYNC.INC}
  877.  
  878.   var
  879.     c : char;
  880.  
  881.   begin
  882.     Async_Init;  { initialize variables }
  883.     if not Async_Open(1, 1200, 'E', 7, 1) then  {open communications
  884.   port}
  885.       begin
  886.         writeln('**ERROR: Async_Open failed');
  887.         halt
  888.       end;
  889.  
  890.     writeln('TTY Emulation begins now...');
  891.     writeln('Press any function key to terminate...');
  892.  
  893.     repeat
  894.       if Async_Buffer_Check(c) then
  895.         case c of
  896.           #000 : ;  { strip incoming nulls }
  897.           #010 : ;  { strip incoming line feeds }
  898.           #012 : ClrScr;  { clear screen on a form feed }
  899.           #013 : Writeln  { handle carriage return as CR/LF }
  900.         else
  901.           write(c)  { else write incoming char to the screen }
  902.         end; { case }
  903.       if KeyPressed then
  904.         begin
  905.           Read(Kbd, c);
  906.           if c = #027 then  { handle IBM Extended Ascii codes }
  907.             begin
  908.               Read(Kbd, c);  { clear the rest of the extended code }
  909.               Async_Close;   { reset the interrupt system, etc. }
  910.               Writeln('End of TTY Emulation...');
  911.               Writeln('Max Buffer Used = ', Async_MaxBufferUsed);
  912.               halt          { terminate the program }
  913.             end
  914.           else
  915.             Async_Send(c)
  916.         end
  917.     until FALSE
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  934.   VERSION : 3.0xx
  935.        OS : PC-DOS
  936.      DATE : August 1, 1986                             PAGE : 15/15
  937.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  938.  
  939.  
  940.  
  941.  
  942.   end.
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.